﻿using System.Windows;
using GameEngine.Clients.Silverlight;
using GameEngine.Clients.Silverlight.View;
using GameEngine.Clients.Silverlight.View.Components;
using GameEngine.Model;
using GameEngine.Model.Data;
using GameEngine.View;
using MySettlers.Commands;
using MySettlers.Things;
using MySettlers.View;
using MySettlers.View.Components;
using GameEngine.Model.Data.implementation;
using MapEngine;
using GameEngine.View.Components;
using System.Windows.Controls;
using System.IO;
using GameEngine;
using MySettlers.Model;
using System;
using SilverlightResources;
using System.Windows.Media;
using System.Collections.Generic;

namespace MySettlers
{
    public class MyFacade : SilverlightFacade
    {
        public IWorldVOId currentWorldId;
        public IWorldVOId currentWorldMiniMapId;

        #region names
        public const string MainPageMediatorName = "MainPageMediator";
        public const string EditorPageMediatorName = "EditorPageMediator";
        public const string EditorPreSettingsPageMediatorName = "EditorPreSettingsPageMediatorName";
        public const string EditorEditPageMediatorName = "EditorEditPageMediatorName";
        public const string PlayPageMediatorName = "PlayPageMediator";
        #endregion

        #region ids
        public ThingTypeVOId peasantMaleTypeId;
        public ThingTypeVOId peasantFemaleTypeId;
        public ThingTypeVOId heroMaleTypeId;
        public ThingTypeVOId heroFemaleTypeId;
        
        public ThingTypeVOId castleTypeId;
        public ThingTypeVOId wheatFarmTypeId;
        public ThingTypeVOId pigFarmTypeId;
        public ThingTypeVOId millTypeId;
        public ThingTypeVOId bakeryTypeId;
        public ThingTypeVOId wellTypeId;
        public ThingTypeVOId slaughterHouseTypeId;

        public ThingTypeVOId grassTypeId;
        public ThingTypeVOId houseTypeId; 
        public ThingTypeVOId fieldTypeId; 
        public ThingTypeVOId treeTypeId;
        public ThingTypeVOId bushTypeId;
        #endregion

        #region commands
        public const string PAGE_MAIN_IN_COMMAND = "PAGE_MAIN_IN_COMMAND";
        public const string PAGE_MAIN_OUT_COMMAND = "PAGE_MAIN_OUT_COMMAND";


        public const string PAGE_GAMEMAINMENU_IN_COMMAND = "PAGE_GAMEMAINMENU_IN_COMMAND";
        public const string PAGE_GAMEMAINMENU_OUT_COMMAND = "PAGE_GAMEMAINMENU_OUT_COMMAND";

        public const string PAGE_GAME_IN_COMMAND = "PAGE_GAME_IN_COMMAND";
        public const string PAGE_GAME_OUT_COMMAND = "PAGE_GAME_OUT_COMMAND";

        public const string PAGE_GAME_NEWTHING_IN_COMMAND = "PAGE_GAME_NEWTHING_IN_COMMAND";
        public const string PAGE_GAME_NEWTHING_OUT_COMMAND = "PAGE_GAME_NEWTHING_OUT_COMMAND";

        
        public const string PAGE_EDITORMAINMENU_IN_COMMAND = "PAGE_EDITOR_IN_COMMAND";
        public const string PAGE_EDITORMAINMENU_OUT_COMMAND = "PAGE_EDITOR_OUT_COMMAND";

        public const string PAGE_EDITORNEWGAME_IN_COMMAND = "PAGE_EDITORNEWGAME_IN_COMMAND";
        public const string PAGE_EDITORNEWGAME_OUT_COMMAND = "PAGE_EDITORNEWGAME_OUT_COMMAND";
        public const string PAGE_EDITORLOADGAME_IN_COMMAND = "PAGE_EDITORLOADGAME_IN_COMMAND";
        public const string PAGE_EDITORLOADGAME_OUT_COMMAND = "PAGE_EDITORLOADGAME_OUT_COMMAND";

        public const string PAGE_EDITOREDITGAME_IN_COMMAND = "PAGE_EDITOREDITGAME_IN_COMMAND";
        public const string PAGE_EDITOREDITGAME_OUT_COMMAND = "PAGE_EDITOREDITGAME_OUT_COMMAND";
        #endregion

        public MyFacade(){
            peasantMaleTypeId = new ThingTypeVOId(MyModel.Instance.CreateNewId()) { Name = "peasantMale" };
            peasantFemaleTypeId = new ThingTypeVOId(MyModel.Instance.CreateNewId()) { Name = "peasantFemale" };
            heroMaleTypeId = new ThingTypeVOId(MyModel.Instance.CreateNewId()) { Name = "heroMale" };
            heroFemaleTypeId = new ThingTypeVOId(MyModel.Instance.CreateNewId()) { Name = "heroFemale" };
            treeTypeId = new ThingTypeVOId(MyModel.Instance.CreateNewId()) { Name = "tree" };
            grassTypeId = new ThingTypeVOId(MyModel.Instance.CreateNewId()) { Name = "grass" };
            houseTypeId = new ThingTypeVOId(MyModel.Instance.CreateNewId()) { Name = "house" };
            fieldTypeId = new ThingTypeVOId(MyModel.Instance.CreateNewId()) { Name = "field" };
        }

        // Override Singleton Factory method 
        public new static MyFacade Instance
        {
            get
            {
                return SilverlightFacade.Instance as MyFacade;
            }
        }

        protected override void InitializeController()
        {
            base.InitializeController();

            RegisterCommand(FPS_NOTIFICATION, typeof(FPSCommand));//TODO meter isto como evento

            RegisterCommand(PAGE_MAIN_IN_COMMAND, typeof(Page_MainMenu_In_Command));
            RegisterCommand(PAGE_MAIN_OUT_COMMAND, typeof(Page_MainMenu_Out_Command));

            RegisterCommand(PAGE_GAMEMAINMENU_IN_COMMAND, typeof(Page_GameMainMenu_In_Command));
            RegisterCommand(PAGE_GAMEMAINMENU_OUT_COMMAND, typeof(Page_GameMainMenu_Out_Command));
            //RegisterCommand(PAGE_GAMENEW_IN_COMMAND, typeof(Page_GameNew_In_Command));
            //RegisterCommand(PAGE_GAMENEW_OUT_COMMAND, typeof(Page_GameNew_Out_Command));
            //RegisterCommand(PAGE_GAMELOAD_IN_COMMAND, typeof(Page_GameLoad_In_Command));
            //RegisterCommand(PAGE_GAMELOAD_OUT_COMMAND, typeof(Page_GameLoad_Out_Command));
            RegisterCommand(PAGE_GAME_IN_COMMAND, typeof(Page_Game_In_Command));
            RegisterCommand(PAGE_GAME_OUT_COMMAND, typeof(Page_Game_Out_Command));
            RegisterCommand(PAGE_GAME_NEWTHING_IN_COMMAND, typeof(Page_Game_NewThing_In_Command));
            RegisterCommand(PAGE_GAME_NEWTHING_OUT_COMMAND, typeof(Page_Game_NewThing_Out_Command));

            RegisterCommand(PAGE_EDITORMAINMENU_IN_COMMAND, typeof(Page_EditorMainMenu_In_Command));
            RegisterCommand(PAGE_EDITORMAINMENU_OUT_COMMAND, typeof(Page_EditorMainMenu_Out_Command));
            RegisterCommand(PAGE_EDITORNEWGAME_IN_COMMAND, typeof(Page_EditorNewGame_In_Command));
            RegisterCommand(PAGE_EDITORNEWGAME_OUT_COMMAND, typeof(Page_EditorNewGame_Out_Command));
            RegisterCommand(PAGE_EDITORLOADGAME_IN_COMMAND, typeof(Page_EditorLoadGame_In_Command));
            RegisterCommand(PAGE_EDITORLOADGAME_OUT_COMMAND, typeof(Page_EditorLoadGame_Out_Command));
            RegisterCommand(PAGE_EDITOREDITGAME_IN_COMMAND, typeof(Page_EditorEditGame_In_Command));
            RegisterCommand(PAGE_EDITOREDITGAME_OUT_COMMAND, typeof(Page_EditorEditGame_Out_Command));

            //RegisterCommand(PAGE_EDITORNEWLEVEL_IN_COMMAND, typeof(Page_EditorNewLevel_In_Command));
            //RegisterCommand(PAGE_EDITORNEWLEVEL_OUT_COMMAND, typeof(Page_EditorNewLevel_Out_Command));
            //RegisterCommand(PAGE_EDITORLOADLEVEL_IN_COMMAND, typeof(Page_EditorLoadLevel_In_Command));
            //RegisterCommand(PAGE_EDITORLOADLEVEL_OUT_COMMAND, typeof(Page_EditorLoadLevel_Out_Command));
        }

        override protected void CreateModelFacade()
        {
            new MyModel();
        }

        protected override void CreateViewFacade()
        {
            new MyViewFacade();
        }

        public IGameVO<int> AddGameDefaultData(IGameVO<int> game) {

            game.MaxHeight = 50;
            game.MinHeight = 0;

            #region resources
            //game.Resources.Add("maleandfemalefinal.png", new Image() { Source = new BitmapImage(new Uri("/Resources/maleandfemalefinal.png",UriKind.Relative)) });
            //game.Resources.Add("maleandfemalefinal.png", new Image() { Source = new BitmapImage(new Uri("/Resources/tux.png", UriKind.Relative)) });
            //Application.Current.Resources.Add("maleandfemalefinal.png", new Image() { Source = new BitmapImage(new Uri("/Resources/maleandfemalefinal.png", UriKind.Relative)) });
            #endregion

            #region Views

            var houseView = MyShapes.createHouse(SilverlightModelFacade.Instance.CreateNewId(), "house", new Point3d(new Point(20, 20), 15), new Point3d(new Point(22, 22), 10), Colors.White, Colors.Red);
            var fieldView = MyShapes.createView(SilverlightModelFacade.Instance.CreateNewId(), "field", new List<IShapeVO>(){
                new ShapeVO(new ShapeVOId(MyShapes.NewShapeID), new ShapeTypeVOId(ItemUC.ShapeTypeCube))
            {
                Position = new MapEngine.Point3d(),
                TypeModifiers = ItemUC.createCubeModifiers(new Point3d(new Point(0,0),1), new Point3d(new Point(30,30),1), Colors.Yellow)
            }});

            var treeView = MyShapes.createTree(MyModel.Instance.CreateNewId(),"tree",new Point3d(new Point(5,5),10),new Point(20,20));
            var grassView = MyShapes.createGrass(MyModel.Instance.CreateNewId(),"grass",new Point(5,5));            
            var redTeamPeasantView = SpriteMaleAndFemale.createMaleView(MyModel.Instance.CreateNewId(),"Red Team Peasant");
            var blueTeamPeasantView = SpriteMaleAndFemale.createFemaleView(MyModel.Instance.CreateNewId(), "Blue Team Peasant");
            game.Views.Add(houseView);
            game.Views.Add(treeView);
            game.Views.Add(grassView);
            game.Views.Add(fieldView);
            game.Views.Add(redTeamPeasantView);
            game.Views.Add(blueTeamPeasantView);
            #endregion

            #region Types
            //Add ThingTypes
            PeasantTypeVO redTeamPeasantTypeVO = new PeasantTypeVO(MyFacade.Instance.peasantMaleTypeId, redTeamPeasantView.Id)
            {
                Velocity = 0.15f
            };
            game.ThingTypes.Add(redTeamPeasantTypeVO);
            PeasantTypeVO blueTeamPeasantTypeVO = new PeasantTypeVO(MyFacade.Instance.peasantFemaleTypeId, redTeamPeasantView.Id)
            {
                Velocity = 0.15f
            };
            game.ThingTypes.Add(blueTeamPeasantTypeVO);

            ThingTypeVO<int> houseTypeVO = new BuildingTypeVO(MyFacade.Instance.houseTypeId)
            {
                ViewId = houseView.Id
            };
            game.ThingTypes.Add(houseTypeVO);

            ThingTypeVO<int> fieldTypeVO = new ThingTypeVO<int>(MyFacade.Instance.fieldTypeId)
            {
                ViewId = fieldView.Id
            };
            game.ThingTypes.Add(fieldTypeVO);

            //PeasantTypeVO peasantFemaleTypeVO = new PeasantTypeVO(peasantFemaleType, fieldView.Id)
            //{
            //    Velocity = 0.1f
            //};
            //game.ThingTypes.Add(peasantFemaleTypeVO.Id, peasantFemaleTypeVO);

            ThingTypeVO<int> grassType = new ThingTypeVO<int>(MyFacade.Instance.grassTypeId)
            {
                ViewId = grassView.Id
            };
            game.ThingTypes.Add(grassType);

            ThingTypeVO<int> treeType = new ThingTypeVO<int>(MyFacade.Instance.treeTypeId)
            {
                ViewId = treeView.Id
            };
            game.ThingTypes.Add(treeType);
            #endregion

            return game;
        }

    }

    public class MyViewFacade : SilverlightViewFacade
    {

        public override IGameView<int, FrameworkElement> CreateGameView()
        {
            return new MyGameUC();
        }

        public override ILevelView<int, FrameworkElement> CreateLevelView()
        {
            return new MyLevelUC();
        }

        public override GameMediator<int, FrameworkElement> 
            CreateGameMediator(
            IGameDataProxy<int> dataProxy, 
            //LevelMediator<MyLevelUC, WorldUC, MapUC, ItemUC, int, FrameworkElement> levelMed, 
            IGameView<int, FrameworkElement> view)
        {
            return new MyGameMediator(dataProxy, view);
        }

        public override LevelMediator<int, FrameworkElement> CreateLevelMediator(ILevelDataProxy<int> dataProxy, System.Collections.Generic.IDictionary<IWorldVOId, WorldMediator<int, FrameworkElement>> worldMeds, ILevelView<int, FrameworkElement> view)
        {
            return new MyLevelMediator(dataProxy,worldMeds,view);
        }
    }

    public class MyFacadeHelper : SilverlightApplicationFacadeHelper
    {

        public static void Start(Application app)
        {
            MyFacade.Instance.SendNotification(MyFacade.PAGE_MAIN_IN_COMMAND, app);
        }
    }

    public class MyModel : SilverlightModelFacade
    {

        public override GameEngine.Model.IThingDataProxy<int> CreateThingDataProxy(IThingVO<int> vo)
        {
            if (vo.GetType().GUID == typeof(PeasantVO).GUID)
            {
                return new PeasantDataProxy(vo as PeasantVO);
            }
            else if (vo.GetType().GUID == typeof(BuildingVO).GUID)
            {
                return new BuildingDataProxy(vo as BuildingVO);
            }
            return base.CreateThingDataProxy(vo);
        }

        public override IThingTypeDataProxy<int> CreateThingTypeDataProxy(IThingTypeVO<int> vo)
        {
            if (vo.GetType().GUID == typeof(PeasantTypeVO).GUID)
            {
                return new PeasantTypeDataProxy(
                        vo as PeasantTypeVO,
                        CreateViewDataProxy(Game.Views[vo.ViewId]));
            }
            else if (vo.GetType().GUID == typeof(BuildingTypeVO).GUID)
            {
                return new BuildingTypeDataProxy(
                        vo as BuildingTypeVO,
                        CreateViewDataProxy(Game.Views[vo.ViewId]));
            }
            return base.CreateThingTypeDataProxy(vo);
        }

        public override IThingVO<int> CreateThingVO(IThingVOId<int> id, IThingTypeVOId typeId)
        {
            if (Game.ThingTypes[typeId].GetType().GUID == typeof(PeasantTypeVO).GUID)
            {
                return new PeasantVO(id,typeId);
            }
            else if (Game.ThingTypes[typeId].GetType().GUID == typeof(BuildingTypeVO).GUID)
            {
                return new BuildingVO(id, typeId);
            }
            return base.CreateThingVO(id, typeId);
        }

        public override ILevelDataProxy<int> CreateLevelDataProxy(ILevelVO<int> vo)
        {
            return new MyLevelDataProxy(vo);
        }

        public override void InitializeWorldActions()
        {
            base.InitializeWorldActions();
            EngineDataProxy<int>.Instance.AddWorldAction(
                   new EngineDataProxy<int>.WorldAction(
                       typeof(BuildingDataProxy),
                       BuildingDataProxy.Action,
                       1000
                       ));
            EngineDataProxy<int>.Instance.AddWorldAction(
                   new EngineDataProxy<int>.WorldAction(
                       typeof(PeasantDataProxy),
                       PeasantDataProxy.Action,
                       500
                       ));
        }

        public override IGameVO<int> CreateGameVO(IGameVOId id)
        {
            return new MyGameVO(id);
        }

        public override IGameVO<int> CreateGameVO()
        {
            return new MyGameVO();
        }
    }

    public class MyGameVO : GameVO<int> {
        public MyGameVO(IGameVOId id) : base(id) { 
        }

        public MyGameVO() : base() { }

        public override object createInstance(String className, params object[] args)
        {
            var classType = Type.GetType(className);
            if (classType == null)
                return base.createInstance(className, args);
            return Activator.CreateInstance(classType, args);
        }
    }

    public class SavedGameFile{
        public String FileName{
            get;
            set;
        }

        public override string  ToString()
{
            String result = FileName.Replace(".txt","");
            result = result.Substring(result.LastIndexOf('.')+1);
            return result;
}
    }
}
